#include "can_alyst_ii.h"
#include "ControlCAN.h"
#include "sys.h"

#include <QDebug>
#include <QMap>
#include <QTimer>

can_alyst_ii::can_alyst_ii(void)
{
    /* 收发定时器 */

    auto_receive_timer = new QTimer(this);
    auto_transmit_timer = new QTimer(this);

    #if AUTO_RECEIVE_TRANSMIT_USE_SIGNALS

        /* 自动读取定时器启动 */
        auto_receive_timer->start(30);
        /* 自动发送定时器启动 */
        auto_transmit_timer->start(500);

    #else

        /* 自动收发定时器启动停止消息 */
        connect(this, &can_alyst_ii::auto_receive_ctrl_signals, this, &can_alyst_ii::auto_receive_timer_ctrl);
        connect(this, &can_alyst_ii::auto_transmit_ctrl_signals, this, &can_alyst_ii::auto_transmit_timer_ctrl);

    #endif

    /* 收发定时器 */
    connect(auto_receive_timer, SIGNAL(timeout()), this, SLOT(auto_receive()));
    connect(auto_transmit_timer, SIGNAL(timeout()), this, SLOT(auto_transmit()));

    /* 注册信号量变量类型 */

    qRegisterMetaType<VCI_CAN_OBJ>("VCI_CAN_OBJ");
    qRegisterMetaType<ulong>("ulong");

    /* 设置波特率字典 */

    baudrate_timing_0_map.insert("10Kbps", 0x31);
    baudrate_timing_0_map.insert("20Kbps", 0x18);
    baudrate_timing_0_map.insert("40Kbps", 0x87);
    baudrate_timing_0_map.insert("50Kbps", 0x09);
    baudrate_timing_0_map.insert("80Kbps", 0x83);
    baudrate_timing_0_map.insert("100Kbps", 0x04);
    baudrate_timing_0_map.insert("125Kbps", 0x03);
    baudrate_timing_0_map.insert("200Kbps", 0x81);
    baudrate_timing_0_map.insert("250Kbps", 0x01);
    baudrate_timing_0_map.insert("400Kbps", 0x80);
    baudrate_timing_0_map.insert("500Kbps", 0x00);
    baudrate_timing_0_map.insert("666Kbps", 0x80);
    baudrate_timing_0_map.insert("800Kbps", 0x00);
    baudrate_timing_0_map.insert("1000Kbps", 0x00);
    baudrate_timing_0_map.insert("33.33Kbps", 0x09);
    baudrate_timing_0_map.insert("66.66Kbps", 0x04);
    baudrate_timing_0_map.insert("83.33Kbps", 0x03);

    baudrate_timing_1_map.insert("10Kbps", 0x1C);
    baudrate_timing_1_map.insert("20Kbps", 0x1C);
    baudrate_timing_1_map.insert("40Kbps", 0xFF);
    baudrate_timing_1_map.insert("50Kbps", 0x1C);
    baudrate_timing_1_map.insert("80Kbps", 0xFF);
    baudrate_timing_1_map.insert("100Kbps", 0x1C);
    baudrate_timing_1_map.insert("125Kbps", 0x1C);
    baudrate_timing_1_map.insert("200Kbps", 0xFA);
    baudrate_timing_1_map.insert("250Kbps", 0x1C);
    baudrate_timing_1_map.insert("400Kbps", 0xFA);
    baudrate_timing_1_map.insert("500Kbps", 0x1C);
    baudrate_timing_1_map.insert("666Kbps", 0xB6);
    baudrate_timing_1_map.insert("800Kbps", 0x16);
    baudrate_timing_1_map.insert("1000Kbps", 0x14);
    baudrate_timing_1_map.insert("33.33Kbps", 0x6F);
    baudrate_timing_1_map.insert("66.66Kbps", 0x6F);
    baudrate_timing_1_map.insert("83.33Kbps", 0x6F);

}

can_alyst_ii::~can_alyst_ii()
{

}

/* 打开设备 */
void can_alyst_ii::open_device(void)
{
    ulong return_msg;

    return_msg = VCI_OpenDevice(device_type, device_index, 0);

    if(return_msg)
    {
        qDebug("打开CAN分析仪：成功");
    }
    else
    {
        qDebug("打开CAN分析仪：错误");
    }

}

/* 关闭设备 */
void can_alyst_ii::close_device(void)
{
    ulong return_msg;

    return_msg = VCI_CloseDevice(device_type, device_index);

    if(return_msg)
    {
        qDebug("关闭CAN分析仪：成功");
    }
    else
    {
        qDebug("关闭CAN分析仪：错误");
    }
}

/* 清空缓存 */
void can_alyst_ii::clear_buffer(channel_t ch_num)
{
    ulong return_msg;

    return_msg = VCI_ClearBuffer(device_type, device_index, (ulong)ch_num);

    if(return_msg)
    {
        qDebug("清除通道%d缓存：成功", 1 + (int)ch_num);
    }
    else
    {
        qDebug("清除通道%d缓存：错误", 1 + (int)ch_num);
    }
}

/* 读取板卡信息 */
void can_alyst_ii::read_board_info(void)
{
    ulong return_msg;

    return_msg = VCI_ReadBoardInfo(device_type, device_index, &vci_board_info);

    if(return_msg)
    {
        qDebug("读取板卡信息：成功");
    }
    else
    {
        qDebug("读取板卡信息：错误");
    }
}

/* 初始化通道 */
void can_alyst_ii::channel_init(channel_t ch_num)
{
    ulong return_msg;
    VCI_INIT_CONFIG vci_init_config;

    vci_init_config.AccCode = parameter_config[(int)ch_num].acc_code;
    vci_init_config.AccMask = parameter_config[(int)ch_num].acc_mask;
    vci_init_config.Filter = parameter_config[(int)ch_num].filter;
    vci_init_config.Timing0 = baudrate_timing_0_map.value(parameter_config[(int)ch_num].baudrate);
    vci_init_config.Timing1 = baudrate_timing_1_map.value(parameter_config[(int)ch_num].baudrate);
    vci_init_config.Mode = parameter_config[(int)ch_num].mode;

    return_msg = VCI_InitCAN(device_type, device_index, (ulong)ch_num, &vci_init_config);

    if(return_msg)
    {
        qDebug("初始化通道%d：成功", 1 + (int)ch_num);
    }
    else
    {
        qDebug("初始化通道%d：错误", 1 + (int)ch_num);
    }
}

/* 打开通道 */
void can_alyst_ii::channel_start(channel_t ch_num)
{
    ulong return_msg;

    return_msg = VCI_StartCAN(device_type, device_index, (ulong)ch_num);

    if(return_msg)
    {
        qDebug("启动通道%d：成功", 1 + (int)ch_num);
    }
    else
    {
        qDebug("启动通道%d：错误", 1 + (int)ch_num);
    }
}

/* 重启通道 */
void can_alyst_ii::channel_reset(channel_t ch_num)
{
    ulong return_msg;

    return_msg = VCI_ResetCAN(device_type, device_index, (ulong)ch_num);

    if(return_msg)
    {
        qDebug("重启通道%d：成功", 1 + (int)ch_num);
    }
    else
    {
        qDebug("重启通道%d：错误", 1 + (int)ch_num);
    }
}

/* 发送数据 */
void can_alyst_ii::transmit(channel_t ch_num, uchar *msg, uchar data_len)
{
    ulong return_msg;
    VCI_CAN_OBJ vci_can_obj;

    vci_can_obj.ID = parameter_config[(int)ch_num].id;
    vci_can_obj.TimeStamp = 0;
    vci_can_obj.TimeFlag = 0;
    vci_can_obj.SendType = (uchar)parameter_config[(int)ch_num].send_type;
    vci_can_obj.RemoteFlag = (uchar)parameter_config[(int)ch_num].frame_type;
    vci_can_obj.ExternFlag = (uchar)parameter_config[(int)ch_num].id_type;
    vci_can_obj.DataLen = data_len;

    for(int loop = 0; loop < data_len; loop++)
    {
        vci_can_obj.Data[loop] = msg[loop];
    }

    return_msg = VCI_Transmit(device_type, device_index, (ulong)ch_num, &vci_can_obj, 1);

    if(return_msg > 0)
    {
        qDebug("通道%d发送：成功 已发送%d字节", 1 + (int)ch_num, (int)return_msg);
    }
    else
    {
        qDebug("通道%d发送：失败 已发送%d字节", 1 + (int)ch_num, (int)return_msg);
    }
}

/* 接收数据 */
void can_alyst_ii::receive(channel_t ch_num)
{
    /* 消息数量 */
    ulong msg_num;

    /* 消息结构体数组 */
    VCI_CAN_OBJ vci_can_obj[2500];

    msg_num = VCI_Receive(device_type, device_index, (ulong)ch_num, vci_can_obj, 2500, 0);

    if(msg_num > 0)
    {
        if(ch_num == ch_1)
        {
            emit ch1_receive_msg_signals(vci_can_obj, msg_num);
        }
        else if(ch_num == ch_2)
        {
            emit ch2_receive_msg_signals(vci_can_obj, msg_num);
        }
    }
    else if((int)msg_num == -1)
    {
        /*
            USB-CAN设备不存在或USB掉线
            可以调用VCI_CloseDevice并重新VCI_OpenDevice
            如此可以达到USB-CAN设备热插拔的效果。
        */
    }
}

/* 自动接收 */
void can_alyst_ii::auto_receive(void)
{
    #if AUTO_RECEIVE_TRANSMIT_USE_SIGNALS

        if(auto_receive_flag)
        {
            /* 读取通道1 */

            receive(ch_1);

            /* 读取通道2 */

            receive(ch_2);
        }

    #else

        /* 读取通道1 */

        receive(ch_1);

        /* 读取通道2 */

        receive(ch_2);

    #endif
}

/* 自动发送 */
void can_alyst_ii::auto_transmit(void)
{
    #if AUTO_RECEIVE_TRANSMIT_USE_SIGNALS

        if(auto_transmit_flag)
        {
            auto_transmit_time_cnt++;

            if(auto_transmit_time_cnt == auto_transmit_time)
            {
                transmit(auto_transmit_dat.ch, auto_transmit_dat.dat, auto_transmit_dat.dat_len);

                auto_transmit_time_cnt = 0;
            }
        }

    #else

        transmit(auto_transmit_dat.ch, auto_transmit_dat.dat, auto_transmit_dat.dat_len);

    #endif
}

#if !AUTO_RECEIVE_TRANSMIT_USE_SIGNALS

void can_alyst_ii::auto_receive_timer_ctrl(bool sw, int tim)
{
    if(sw)
    {
        /* 自动读取定时器启动 */
        auto_receive_timer->start(tim);
    }
    else
    {
        /* 自动读取定时器停止 */
        auto_receive_timer->stop();

        not_use(tim);
    }
}

void can_alyst_ii::auto_transmit_timer_ctrl(bool sw, int tim)
{
    if(sw)
    {
        /* 自动发送定时器启动 */
        auto_transmit_timer->start(tim);
    }
    else
    {
        /* 自动发送定时器停止 */
        auto_transmit_timer->stop();

        not_use(tim);
    }
}

#endif
